package com.hanock.sm.fork2d;

import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory.Options;
import android.graphics.Paint.Align;
import android.opengl.GLUtils;
import android.util.Log;

public class TextureUtil {
	
	private static Options defaultOption;
	private static Options tempOption;
	
	static {
		defaultOption = new Options();
		defaultOption.inScaled = false;
		defaultOption.inPreferredConfig = Config.ARGB_8888;
		
		tempOption = new Options();
		tempOption.inScaled = false;
	}
	
	public static Texture createTexture(GL10 gl, Context context, int resId){
		
		Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resId, defaultOption);
		
		Texture texture = createTexture(gl, bitmap);

		bitmap.recycle();
		
		return texture;
	}
	
	public static Texture createTexture(GL10 gl, Context context, int resId, Options option){
		
		Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resId, option);
		
		Texture texture = createTexture(gl, bitmap);

		bitmap.recycle();
		
		return texture;
	}
	
	public static Texture createTexture(GL10 gl, Context context, int resId, Config config){
		
		tempOption.inPreferredConfig = config;
		Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resId, tempOption);
		
		Texture texture = createTexture(gl, bitmap);

		bitmap.recycle();
		
		return texture;
	}

	public static Texture createTexture(GL10 gl, Bitmap bitmap){
		int[] textureId = new int[1];
		
		gl.glGenTextures(1, textureId, 0);
		gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId[0]);
		
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
		
		Bitmap backBitmap = Bitmap.createBitmap(TextureUtil.getTextureLength(bitmap.getWidth()), TextureUtil.getTextureLength(bitmap.getHeight()), bitmap.getConfig());
		GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, backBitmap, 0);
		backBitmap.recycle();
		
		GLUtils.texSubImage2D(GL10.GL_TEXTURE_2D, 0, 0, 0, bitmap);
		
		Texture texture = new Texture(textureId[0], bitmap.getWidth(), bitmap.getHeight());
		
		return texture;
	}

	public static Texture createTexture(GL10 gl, String text, float fontSize, Align align) {
		if (text.length() == 0){
			text = " ";
		}
		
		Typeface typeface = Typeface.SERIF;
		
        Paint textPaint = new Paint();
        textPaint.setTypeface(typeface);
        textPaint.setTextSize(fontSize);
        textPaint.setAntiAlias(true);
        textPaint.setDither(true);
        textPaint.setColor(Color.WHITE);
        textPaint.setTextAlign(align);
        
        String[] strArr = text.split("\n");

        int measuredTextWidth = 0;

        int ascent = (int) Math.ceil(-textPaint.ascent());  // Paint.ascent is negative, so negate it
        int descent = (int) Math.ceil(textPaint.descent());
        
        for (String str: strArr){
        	int w = (int) Math.ceil(textPaint.measureText(str));
        	if (measuredTextWidth < w){
        		measuredTextWidth = w;
        	}
        }

        int totalWidth = measuredTextWidth;
        int totalHeight = (ascent + descent)*strArr.length;
        int singleHeight = (ascent + descent);
        
        if (totalWidth%2 == 1)
        	totalWidth += 1;
        if (totalHeight%2 == 1)
        	totalHeight += 1;

        Bitmap.Config config = Bitmap.Config.ARGB_8888;
        Bitmap bitmap = Bitmap.createBitmap(totalWidth, totalHeight, config);
        Canvas canvas = new Canvas(bitmap);
        bitmap.eraseColor(0);

        
        //
        float tx = 0;
        switch (align) {
		case LEFT:
			tx = 0;
			break;
			
		case CENTER:
			tx = totalWidth/2;
			break;
			
		case RIGHT:
			tx = totalWidth;
			break;

		default:
			break;
		}
        
        
        //
        for (int i = 0; i < strArr.length; i++){
        	canvas.drawText(strArr[i], tx, singleHeight*i + ascent, textPaint);
        }

        //
        Texture texture = createTexture(gl, bitmap);
        bitmap.recycle();
        return texture;
    }
	
	public static void deleteTexture(GL10 gl, Texture texture){
		int[] tex = new int[]{texture.getTextureId()};
		gl.glDeleteTextures(1, tex, 0);
	}
	
	public static int getTextureLength(int imageLength){
		
		int length = 1;
		
		while (imageLength > length){
			length = length << 1;
		}
		
		return length;
	}
	
	/** Modifies the desRect to fit center */
	public static void fitCenter(Texture texture, Rect srcRect, RectF desRect){
		
		if (texture == null || desRect	== null)
			throw new NullPointerException();
		
		float bw = texture.getImageWidth();
		float bh = texture.getImageHeight();
		
		if (srcRect == null){
			bw = texture.getImageWidth();
			bh = texture.getImageHeight();
		}
		else{
			bw = srcRect.width();
			bh = srcRect.height();
		}
		
		float width = desRect.width();
		float height = MathUtil.height(desRect);
		
		if (bw == 0 || bh == 0 || width == 0 || height == 0)
			return;
		
		float bitmapRatio = bw/bh;
		float canvasRatio = 1f*width/height;
		
		float drawWidth = 0;
		float drawHeight = 0;
		
		if (bitmapRatio > canvasRatio){
			
			drawWidth = width;
			drawHeight = drawWidth/bitmapRatio;
		}
		else{
			drawHeight = height;
			drawWidth = drawHeight*bitmapRatio;
		}
		
		float cx = desRect.centerX();
		float cy = desRect.centerY();
		
		desRect.left = cx - drawWidth/2;
		desRect.right = cx + drawWidth/2;
		desRect.top = cy + drawHeight/2;
		desRect.bottom = cy - drawHeight/2;
		
	}
	
	public static void fitLeft(Texture texture, Rect srcRect, RectF desRect){
		
		if (texture == null || desRect	== null)
			throw new NullPointerException();
		
		float left = desRect.left;
		
		fitCenter(texture, srcRect, desRect);
		
		if (left < desRect.left){
			float dx = desRect.left - left;
			desRect.left -= dx;
			desRect.right -= dx;
		}
	}
}










